package com.yc.framework.config;

import com.yc.framework.security.filter.JwtAuthenticationTokenFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.annotation.Resource;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Resource
    private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authConfig) throws Exception {
        return authConfig.getAuthenticationManager();
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {

        String[] api = {"/captchaImage", "/verify-code", "/email-code", "/register", "/login"};

        http
                // 禁用 CSRF，因为我们通常会在前后端分离的情况下使用 JWT
                .csrf().disable()

                // 无状态会话，使用 JWT 进行认证
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()

                // 设置权限控制规则
                .authorizeRequests()
                // 允许以下公共接口无需认证
                .antMatchers(api).permitAll()
                // 放行Swagger访问路径
                .antMatchers(
                        "/doc.html",                   // Knife4j主页面
                        "/webjars/**",                 // 静态资源
                        "/swagger-resources/**",       // Swagger资源
                        "/v3/api-docs/**",             // OpenAPI 3.0接口文档
                        "/swagger-ui/**",              // Swagger UI
                        "/api/doc.html",               // 如果设置了context-path
                        "/api/webjars/**",
                        "/api/swagger-resources/**",
                        "/api/v3/api-docs/**",
                        "/api/swagger-ui/**"
                ).permitAll()
                // 其他所有请求需要认证
                .anyRequest().authenticated()
                .and()

                // 添加自定义 JWT 认证过滤器
                .addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);

        return http.build();
    }
}
